/*
 * Copyright 2010 Alexander Ulizko
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.ulizko.template.soy.utils;

import com.google.common.collect.Lists;
import com.google.common.collect.Sets;

import java.io.File;
import java.util.List;
import java.util.Set;

/**
 * Container for general-purpose file utilites
 *
 * @author Alexander <alexander@ulizko.com> Ulizko
 *         Date: 07.11.2010
 *         Time: 21:21:25
 */
public class FileUtils {
    /**
     * Used by {@code ensureDirsExistInPath()}. Keeps track of known existing directory paths.
     */
    private static final Set<String> KNOWN_EXISTING_DIRS = Sets.newHashSet();

    /**
     * Check if provided file extension is "soy" (case ignored)
     *
     * @param file File to test
     * @return true if file is non-directory and has soy extension, false otherwise
     */
    public static Boolean isSoyFile(File file) {
        return hasFileExtensionEqualToProvided(file, "soy");
    }

    /**
     * Check if provided file extension is "java" (case ignored)
     *
     * @param file File to test
     * @return true if file is non-directory and has soy extension, false otherwise
     */
    public static Boolean isJavaFile(File file) {
        return hasFileExtensionEqualToProvided(file, "java");
    }

    /**
     * Checks if file has extension
     *
     * @param file      File to check
     * @param extension Any extension (without ".")
     * @return true if file's extension equals to provided, false otherwise
     */
    public static Boolean hasFileExtensionEqualToProvided(File file, String extension) {
        Boolean hasExtension = false;
        String name = file.getName();
        int dotPlace = name.lastIndexOf('.');
        if (!file.isDirectory() && dotPlace > 0) {
            String actualExtension = name.substring(dotPlace + 1);
            if (actualExtension.equalsIgnoreCase(extension)) {
                hasExtension = true;
            }
        }

        return hasExtension;
    }

    /**
     * Retreives every soy file from provided directory and it's subdirectories
     *
     * @param directory Directory to parse
     * @return List of paths to every soy file inside of directory
     */
    public static List<String> retreiveSoyFilePathsFromDirectory(File directory) {
        File[] content = directory.listFiles();

        List<String> result = Lists.newArrayList();
        for (File file : content) {
            if (file.isDirectory()) {
                result.addAll(retreiveSoyFilePathsFromDirectory(file));
            } else {
                if (isSoyFile(file)) {
                    result.add(file.getPath());
                }
            }

        }

        return result;
    }

    /**
     * Ensures that the directories in the given path exist, creating them if necessary.
     * <p/>
     * Note: If the path does not end with the separator char (slash in Linux), then the name at the
     * end is assumed to be the file name, so directories are only created down to its parent.
     * <p/>
     * And again, borrowed from soy BaseUtils.
     *
     * @param path The path for which to ensure directories exist.
     */
    public static void ensureDirsExistInPath(String path) {

        if (path == null || path.length() == 0) {
            throw new AssertionError(
                    "ensureDirsExistInPath called with null or empty path.");
        }

        String dirPath = (path.charAt(path.length() - 1) == File.separatorChar) ?
                path.substring(0, path.length() - 1) : (new File(path)).getParent();
        if (dirPath != null || !KNOWN_EXISTING_DIRS.contains(dirPath)) {
            (new File(dirPath)).mkdirs();
            KNOWN_EXISTING_DIRS.add(dirPath);
        }
    }


}
